require "base_def"
local mysql = require "skynet.db.mysql"

local mysql_tools = {}

--[[
    callstr:  请求的查询名，只能是call语句
    res_sql:  第二句访问字串, 是否要求有返回值     
    dbindex:  请求的db对列，有数据库访问严格前后关系，可使用单一队列， 如为 nil ，轮询访问

    return: 返回两个结果集, 对于有返回参数的存贮过程，只需使用第二个结果集

    例子：
    callstr = "call pr_MatchChagre("..UserId..","..MatchConf["pay_type"]..","..MatchConf["pay_num"]..",@ReturnVal);"
    local res_sql = "select @ReturnVal;"
    local res1, res2 = db.call(sqlstr, res_sql, nil)
    print(res2[1]['@ReturnVal'])

--]]
function mysql_tools:Query(callstr, res_sql, dbindex)
    --skynet.error("mysql_tools Query!")
    if #self.db_pool==0 or callstr==nil then
        log.error("Error---->command.query find db_pool null")
        return nil
    end
    --skynet.error("[dbser] query dbindex ",dbindex)
    if dbindex==nil then
       dbindex = self.db_use_index
       self.db_use_index = self.db_use_index + 1
    end
    --skynet.error("[dbser] query dbindex FFFFFF", dbindex)
    --fixme:这里做的是DB池，后续优化
    local index = math.fmod(tonumber(dbindex), #self.db_pool)
    index = index + 1

    --skynet.error("db query use index:"..index.." max db pool:"..#db_pool)
    --skynet.error("db query:"..callstr)
    local db = self.db_pool[index]
    local ok, db_res = pcall(db.query, db, callstr)
    --log.info("mysql_tools ok=", ok)
    --log.info("mysql_tools db_res=", db_res)
    
    --查询错误
    if not ok or not db_res then
        log.error('query failed:', db_res)
        return
    end
    --空集
    if not next(db_res) then
        return true
    else
        ----语法等错误
        if db_res.errno then
            log.error(callstr .. ' sql maybe syntax or other errors:', db_res.err)
            return
        else
            return true, db_res
        end
    end

     --[[
    --fixme, 多查询后期优化
    local sql_result = nil
   
    if res_sql then
        --如果有查询第二结果，则返回第二个结果
        sql_result = db:Query(res_sql)
    end
   
    return db_res, sql_result
    --]]
end

function mysql_tools:Call(callstr)
    --log.info("mysql_tools:Call callstr=", callstr)
    local ok, ret = self:Query(callstr)
    --[[
        ret 的结构是 {
            [1] = {       --第1个select结果集
                [1] = {},[2] = {}
            },
            [2] = ...,    --第2个select结果集
            ...,          --第n个select结果集
            [n + 1] = {
                server_status = ...
                affected_rows = ...
            },
            mulitresultset = true
        }
    ]]
    if ok and ret then
        --这个结果还是一个数组
        return true, ret     
    else
        log.error('call_pr failed, str:', callstr)
    end
end

function mysql_tools:Connect()
    local mysql_host = skynet.getenv('mysql_host')
    local mysql_port = skynet.getenv('mysql_port')
    local mysql_database = skynet.getenv('mysql_database') 
    local mysql_user = skynet.getenv('mysql_user')
    local mysql_psw  = skynet.getenv('mysql_psw')

    local db = mysql.connect({
        host        = mysql_host,
        port        = tonumber(mysql_port),
        database    = mysql_database,
        user        = mysql_user,
        password    = mysql_psw,
        --数据包最大字节数
        max_packet_size =  1024 * 1024,
        --连接成功的回调函数
        on_connect  =   function(dbself)
                            dbself:query("set charset utf8mb4")
                        end,
    })

    table.insert(self.db_pool, db)
    log.info("db_pool num="..#self.db_pool)
    log.info("mysql_host =", mysql_host)
    log.info("mysql_port =", mysql_port)
    --log.info("db=", db)
end

function mysql_tools:Init()
    --轮询用的db index，永远都是增长的
    self.db_use_index = 1
    self.db_pool = {}

    self:Connect()
end

skynet.start(function()
    skynet.register(".mysql_tools")

    skynet.dispatch("lua", function(session, address, cmd, ...)
        local f = mysql_tools[cmd]
        if f then
            skynet.ret(skynet.pack(f(mysql_tools, ...)))
        else
            skynet.error(string.format("Unknown command %s", tostring(cmd)))
        end
    end)

    mysql_tools:Init()
end)


return mysql_tools